\section{Source/String.c}


\begin{footnotesize}\begin{alltt}
00001 \textcolor{preprocessor}{#include "String.h"}
00002 
00008 \textcolor{keyword}{inline} \textcolor{keywordtype}{int} StrCheckRealloc(S_String *Str, \textcolor{keywordtype}{int} Size)
00009 \{
00010     \textcolor{comment}{/* This function checks if a string needs to allocate more bytes}
00011 \textcolor{comment}{     *  to handle the incoming data, with a size of Size}
00012 \textcolor{comment}{    */}
00013     \textcolor{keywordflow}{if}(Str->Size < Size)
00014     \{
00015         \textcolor{comment}{/* The string does not have enough memory allocated,}
00016 \textcolor{comment}{         *  let's ask for more}
00017 \textcolor{comment}{        */}
00018         \textcolor{keywordtype}{void} *TempPointer = realloc(Str->String, Size);
00019         \textcolor{keywordflow}{if}(TempPointer == NULL)
00020             \textcolor{keywordflow}{return} -1;
00021         Str->String = TempPointer;
00022         Str->Size = Size;
00023     \}
00024     \textcolor{comment}{/* Else the string does not need to be changed, and the }
00025 \textcolor{comment}{     *  pointer and size variables can stay the same}
00026 \textcolor{comment}{    */}
00027     \textcolor{keywordflow}{return} 0;
00028 \}
00029 
00030 S_String *S\_NewString(\textcolor{keywordtype}{char} *String)
00031 \{
00032     \textcolor{comment}{/* Allocate a new S\_String object on the heap,}
00033 \textcolor{comment}{        check the allocation, and return the object (or NULL)}
00034 \textcolor{comment}{    */}
00035     S_String *Ret = malloc(\textcolor{keyword}{sizeof}(Ret));
00036     \textcolor{keywordflow}{if}(Ret == NULL)
00037         \textcolor{keywordflow}{return} NULL;
00038     Ret->String = malloc(\textcolor{keyword}{sizeof}(Ret->String)*strlen(String));
00039     Ret->Size = strlen(String);
00040     \textcolor{keywordflow}{if}(Ret->String == NULL)
00041         \textcolor{keywordflow}{return} NULL;
00042     \textcolor{keywordflow}{if}(S\_SetString(Ret, String) == -1)
00043         \textcolor{keywordflow}{return} NULL;
00044     Ret->Length = strlen(Ret->String);
00045     \textcolor{keywordflow}{return} Ret;
00046 \}
00047 S_String *S\_NewStringSafe(\textcolor{keywordtype}{char} *String, \textcolor{keywordtype}{int} Length)
00048 \{
00049     S_String *Ret = malloc(\textcolor{keyword}{sizeof}(Ret));
00050     \textcolor{keywordflow}{if}(Ret == NULL)
00051         \textcolor{keywordflow}{return} NULL;
00052     Ret->String = malloc(\textcolor{keyword}{sizeof}(Ret->String)*Length);
00053     \textcolor{keywordflow}{if}(Ret->String == NULL)
00054         \textcolor{keywordflow}{return} NULL;
00055     \textcolor{keywordflow}{if}(S\_SetStringSafe(Ret, String, Length) == -1)
00056         \textcolor{keywordflow}{return} NULL;
00057     Ret->Length = Length;
00058     Ret->Size = Length;
00059     \textcolor{keywordflow}{return} Ret;
00060 \}
00061 
00062 \textcolor{keywordtype}{void} S\_FreeString(S_String *String)
00063 \{
00064     \textcolor{comment}{/* Free all of the data that is being used by the S\_String object */}
00065     free(String->String);
00066     free(String);
00067 \}
00068 
00069 \textcolor{keywordtype}{int} S\_SetString(S_String *String, \textcolor{keywordtype}{char} *Str)
00070 \{
00071     \textcolor{keywordtype}{int} \textcolor{comment}{/*Count, */}Size = strlen(Str);
00072     \textcolor{comment}{/*void *TempPointer = realloc(String->String, sizeof(String->String)*Size);}
00073 \textcolor{comment}{    if(TempPointer == NULL)}
00074 \textcolor{comment}{        return -1;}
00075 \textcolor{comment}{    String->String = TempPointer;}
00076 \textcolor{comment}{    */}
00077     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*Size) == -1)
00078         \textcolor{keywordflow}{return} -1;
00079     \textcolor{comment}{/*for(Count = 0; Count < Size; ++Count)}
00080 \textcolor{comment}{    \{}
00081 \textcolor{comment}{        String->String[Count] = Str[Count];}
00082 \textcolor{comment}{    \}*/}
00083     \textcolor{comment}{/* Copy the string over, by now the string is guarenteed to have enough memor
      y */}
00084     memcpy(String->String, Str, Size);
00085     String->Length = Size;
00086     \textcolor{keywordflow}{return} 0;
00087 \}
00088 \textcolor{keywordtype}{int} S\_SetStringS(S_String *String, S_String *SetString)
00089 \{
00090     \textcolor{comment}{/*char *TempPointer = realloc(String->String, sizeof(String->String)*SetStrin
      g->Length);}
00091 \textcolor{comment}{    if(TempPointer == NULL)}
00092 \textcolor{comment}{        return -1;}
00093 \textcolor{comment}{    String->String = TempPointer;*/}
00094     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*SetString->Length) == -1)
00095         \textcolor{keywordflow}{return} -1;
00096     memcpy(String->String, SetString->String, SetString->Length);
00097     String->Length = SetString->Length;
00098     \textcolor{keywordflow}{return} 0;
00099 \}
00100 \textcolor{keywordtype}{int} S\_SetStringSafe(S_String *String, \textcolor{keywordtype}{char} *Str, \textcolor{keywordtype}{int} Length)
00101 \{
00102     \textcolor{comment}{/*int Count;*/}
00103     \textcolor{comment}{/*char *TempPointer = realloc(String->String, sizeof(String->String)*Length);
      }
00104 \textcolor{comment}{    if(TempPointer == NULL)}
00105 \textcolor{comment}{        return -1;}
00106 \textcolor{comment}{    String->String = TempPointer;*/}
00107     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*Length) == -1)
00108         \textcolor{keywordflow}{return} -1;
00109     \textcolor{comment}{/*for(Count = 0; Count < Length; ++Count)}
00110 \textcolor{comment}{    \{}
00111 \textcolor{comment}{        String->String[Count] = Str[Count];}
00112 \textcolor{comment}{    \}*/}
00113     memcpy(String->String, Str, Length);
00114     String->Length = Length;
00115     \textcolor{keywordflow}{return} 0;
00116 \}
00117 
00118 \textcolor{keywordtype}{void} S\_PrintSafe(S_String *String)
00119 \{
00120     \textcolor{comment}{/* Print the string, char by char, so that all of the string will be preserve
      d,}
00121 \textcolor{comment}{        rather than just printf running into a null byte then stopping}
00122 \textcolor{comment}{    */}
00123     \textcolor{keywordtype}{int} Count;
00124     \textcolor{keywordflow}{for}(Count = 0; Count < String->Length; ++Count)
00125     \{
00126         printf(\textcolor{stringliteral}{"%c"}, String->String[Count]);
00127     \}
00128 \}
00129 
00130 \textcolor{keywordtype}{int} S\_AppendString(S_String *String, \textcolor{keywordtype}{char} *Str)
00131 \{
00132     \textcolor{keywordtype}{int} Length = strlen(Str);
00133     \textcolor{comment}{/*char *TempPointer = realloc(String->String, sizeof(String->String)*(String-
      >Length+Length));}
00134 \textcolor{comment}{    if(TempPointer == NULL)}
00135 \textcolor{comment}{        return -1;}
00136 \textcolor{comment}{    String->String = TempPointer;*/}
00137     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*(String->Length+Length)) ==
       -1)
00138         \textcolor{keywordflow}{return} -1;
00139     \textcolor{comment}{/* Increase the string pointer by the length of the string, and then append t
      he new string to that pointer */}
00140     memcpy(String->String + String->Length-1, Str, Length);
00141     String->Length += Length;
00142     \textcolor{keywordflow}{return} 0;
00143 \}
00144 
00145 \textcolor{keywordtype}{int} S\_AppendStringS(S_String *Str, S_String *AppendString)
00146 \{
00147     \textcolor{comment}{/*char *TempPointer = realloc(Str->String, sizeof(Str->String)*(Str->Length+A
      ppendString->Length));}
00148 \textcolor{comment}{    if(TempPointer == NULL)}
00149 \textcolor{comment}{        return -1;}
00150 \textcolor{comment}{    Str->String = TempPointer;*/}
00151     \textcolor{keywordflow}{if}(StrCheckRealloc(Str, \textcolor{keyword}{sizeof}(Str->String)*(Str->Length+AppendString->
      Length)) == -1)
00152         \textcolor{keywordflow}{return} -1;
00153     memcpy(Str->String + Str->Length, AppendString->String, AppendString->Length)
      ;
00154     \textcolor{keywordflow}{return} 0;
00155 \}
00156 \textcolor{keywordtype}{int} S\_AppendStringSafe(S_String *String, \textcolor{keywordtype}{char} *Str, \textcolor{keywordtype}{int} Length)
00157 \{
00158     \textcolor{comment}{/*char *TempPointer = realloc(String->String, sizeof(String->String)*(String-
      >Length+Length));}
00159 \textcolor{comment}{    if(TempPointer == NULL)}
00160 \textcolor{comment}{        return -1;}
00161 \textcolor{comment}{    String->String = TempPointer;*/}
00162     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*(String->Length+Length)) ==
       -1)
00163         \textcolor{keywordflow}{return} -1;
00164     memcpy(String->String + String->Length, Str, Length);
00165     \textcolor{keywordflow}{return} 0; 
00166 \}
00167 
00168 \textcolor{keywordtype}{int} S\_InsertString(S_String *String, \textcolor{keywordtype}{int} Offset, \textcolor{keywordtype}{char} *Str)
00169 \{
00170     \textcolor{comment}{/*FIXME:}
00171 \textcolor{comment}{        This function could be changed to not use any Temp arrays,}
00172 \textcolor{comment}{        and just relying on the optomisations of the C libraries}
00173 \textcolor{comment}{        memmove and memcpy}
00174 \textcolor{comment}{    */}
00175     \textcolor{keywordflow}{if}(Offset > 0)
00176     \{
00177         \textcolor{comment}{/* Make enough space for the original string, then copy over the original
       string in two sections */}
00178         \textcolor{keywordtype}{char} Temp1[Offset];
00179         memcpy(Temp1, String->String, Offset);
00180         \textcolor{keywordtype}{char} Temp2[String->Length-Offset];
00181         memcpy(Temp2, String->String+Offset, String->Length - Offset+1);
00182         \textcolor{comment}{/*void *TempPointer = realloc(String->String, sizeof(String->String)*Stri
      ng->Length+strlen(Str));}
00183 \textcolor{comment}{        if(TempPointer == NULL)}
00184 \textcolor{comment}{            return -1;}
00185 \textcolor{comment}{        String->String = TempPointer;*/}
00186         \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*(String->Length+strlen(
      Str))) == -1)
00187             \textcolor{keywordflow}{return} -1;
00188         \textcolor{comment}{/* Put all the strings back, in the (new) correct order */}
00189         memcpy(String->String, Temp1, Offset);
00190         memcpy(String->String + Offset, Str, strlen(Str));
00191         memcpy(String->String + Offset + strlen(Str), Temp2, String->Length-Offse
      t);
00192         String->Length += strlen(Str);
00193         \textcolor{keywordflow}{return} 0;
00194     \}   
00195     \textcolor{keywordflow}{else}
00196     \{
00197         \textcolor{keywordflow}{return} S\_PrependString(String, Str);
00198     \}
00199 \}
00200 \textcolor{keywordtype}{int} S\_InsertStringS(S_String *String, \textcolor{keywordtype}{int} Offset, S_String *InsertString)
00201 \{
00202     \textcolor{keywordflow}{if}(Offset > 0)
00203     \{
00204         \textcolor{keywordtype}{char} Temp1[Offset];
00205         memcpy(Temp1, String->String, Offset);
00206         \textcolor{keywordtype}{char} Temp2[String->Length-Offset];
00207         memcpy(Temp2, String->String+Offset, String->Length - Offset+1);
00208         \textcolor{comment}{/*void *TempPointer = realloc(String->String, sizeof(String->String)*Stri
      ng->Length+InsertString->Length);}
00209 \textcolor{comment}{        if(TempPointer == NULL)}
00210 \textcolor{comment}{            return -1;}
00211 \textcolor{comment}{        String->String = TempPointer;*/}
00212         \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*(String->Length+InsertS
      tring->Length)) == -1)
00213             \textcolor{keywordflow}{return} -1;
00214         memcpy(String->String, Temp1, Offset);
00215         memcpy(String->String + Offset, InsertString->String, InsertString->
      Length);
00216         memcpy(String->String + Offset + InsertString->Length, Temp2, String->
      Length-Offset);
00217         String->Length += InsertString->Length;
00218         \textcolor{keywordflow}{return} 0;
00219     \}
00220     \textcolor{keywordflow}{else}
00221     \{
00222         \textcolor{keywordflow}{return} S\_PrependStringS(String, InsertString);
00223     \}
00224 \}
00225 
00226 \textcolor{keywordtype}{int} S\_InsertStringSafe(S_String *String, \textcolor{keywordtype}{int} Offset, \textcolor{keywordtype}{char} *Str, \textcolor{keywordtype}{int} Length)
00227 \{
00228     \textcolor{keywordflow}{if}(Offset > 0)
00229     \{
00230         \textcolor{keywordtype}{char} Temp1[Offset];
00231         \textcolor{keywordtype}{char} Temp2[String->Length-Offset];
00232         memcpy(Temp1, String->String, Offset);
00233         memcpy(Temp2, String->String+Offset, String->Length - Offset+1);
00234         \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*(String->Length+Length)
      ) == -1)
00235             \textcolor{keywordflow}{return} -1;
00236         memcpy(String->String, Temp1, Offset);
00237         memcpy(String->String + Offset, Str, Length);
00238         memcpy(String->String + Offset + Length, Temp2, String->Length - Offset);
      
00239         String->Length += Length;
00240         \textcolor{keywordflow}{return} 0;
00241     \}
00242     \textcolor{keywordflow}{else}
00243     \{
00244         \textcolor{keywordflow}{return} S\_PrependStringSafe(String, Str, Length);
00245     \}
00246 \}
00247 
00248 \textcolor{keywordtype}{int} S\_PrependString(S_String *String, \textcolor{keywordtype}{char} *Str)
00249 \{
00250     \textcolor{comment}{/* FIXME:}
00251 \textcolor{comment}{        The prepend functions are quite slow, due to the}
00252 \textcolor{comment}{        shifting of the whole string by an arbritary amount.}
00253 \textcolor{comment}{        Optomisation ideas welcome}
00254 \textcolor{comment}{    */}
00255     \textcolor{keywordtype}{int} Size =strlen(Str);
00256     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*Size+String->Length) == -1)
      
00257         \textcolor{keywordflow}{return} -1;
00258     \textcolor{comment}{/* Move the string that is already present to an offset of the length of the 
      prepended string*/}
00259     memmove(String->String + Size, String->String, String->Length);
00260     \textcolor{comment}{/* Copy the prepended string into the start of the original string */}
00261     memcpy(String->String, Str, Size);
00262     String->Length += Size;
00263     \textcolor{keywordflow}{return} 0;
00264 \}
00265 \textcolor{keywordtype}{int} S\_PrependStringS(S_String *String, S_String *PString)
00266 \{
00267     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*PString->Length+String->
      Length) == -1)
00268         \textcolor{keywordflow}{return} -1;
00269     memmove(String->String+PString->Length, String->String, String->Length);
00270     memcpy(String->String, PString->String, PString->Length);
00271     String->Length += PString->Length;
00272     \textcolor{keywordflow}{return} 0;
00273 \}
00274 \textcolor{keywordtype}{int} S\_PrependStringSafe(S_String *String, \textcolor{keywordtype}{char} *Str, \textcolor{keywordtype}{int} Length)
00275 \{
00276     \textcolor{keywordflow}{if}(StrCheckRealloc(String, \textcolor{keyword}{sizeof}(String->String)*Length+String->Length) == -
      1)
00277         \textcolor{keywordflow}{return} -1;
00278     memmove(String->String+Length, String->String, String->Length);
00279     memcpy(String->String, Str, Length);
00280     String->Length += Length;
00281     \textcolor{keywordflow}{return} 0;
00282 \}
00283 
00284 \textcolor{keywordtype}{int} S\_SetSize(S_String *String, \textcolor{keywordtype}{int} Size)
00285 \{
00286     \textcolor{comment}{/* Set the capacity of the string, note that this is not the same as the leng
      th of the string */}
00287     \textcolor{keywordflow}{if}(String->Size == Size)
00288         \textcolor{keywordflow}{return} 0;
00289     \textcolor{keywordtype}{void} *TempPointer = realloc(String->String, \textcolor{keyword}{sizeof}(String->String)*Size);
00290     \textcolor{keywordflow}{if}(TempPointer == NULL)
00291         \textcolor{keywordflow}{return} -1;
00292     String->String = TempPointer;
00293     String->Size = Size;
00294     \textcolor{keywordflow}{return} 0;
00295 \}
00296 
00297 \textcolor{comment}{/*}
00298 \textcolor{comment}{char S\_At(S\_String *String, int At)}
00299 \textcolor{comment}{\{}
00300 \textcolor{comment}{    return String->String[At];}
00301 \textcolor{comment}{\} This function is now a macro */}
00302 
00303 \textcolor{keywordtype}{void} S\_StringReverse(S_String *String)
00304 \{
00305     \textcolor{keywordtype}{char} *Front, *Back;
00306     \textcolor{keywordflow}{for}(Front = String->String, Back = String->String + String->Length -1;
00307         Front < Back;
00308         ++Front, --Back)
00309     \{   
00310         \textcolor{keywordtype}{char} Tmp;
00311         Tmp = *Front;
00312         *Front = *Back;
00313         *Back = Tmp;
00314     \}
00315 \}
00316 
00317 \textcolor{keywordtype}{int} S\_FindFirstC(S_String *String, \textcolor{keywordtype}{char} Search)
00318 \{
00319     \textcolor{comment}{/* Go from the start comparing bytes */}
00320     \textcolor{keywordtype}{int} Count = 0;
00321     \textcolor{keywordflow}{while}(Count < String->Length)
00322     \{
00323         \textcolor{keywordflow}{if}(String->String[Count] == Search)
00324             \textcolor{keywordflow}{return} Count;
00325         ++Count;
00326     \}
00327     \textcolor{comment}{/* No identical byte was found */}
00328     \textcolor{keywordflow}{return} -1;
00329 \}
00330 \textcolor{keywordtype}{int} S\_FindLastC(S_String *String, \textcolor{keywordtype}{char} Search)
00331 \{
00332     \textcolor{comment}{/* Start at the end comparing bytes */}
00333     \textcolor{keywordtype}{int} Count = String->Length - 1;
00334     \textcolor{keywordflow}{while}(Count >= 0)
00335     \{
00336         \textcolor{keywordflow}{if}(String->String[Count] == Search)
00337             \textcolor{keywordflow}{return} Count;
00338         --Count;
00339     \}
00340     \textcolor{keywordflow}{return} -1;
00341 \}
00342 \textcolor{keywordtype}{int} S\_FindFirst(S_String *String, \textcolor{keywordtype}{char} *Search)
00343 \{
00344     \textcolor{keywordtype}{int} Count = 0, Size = strlen(Search);
00345     \textcolor{keywordflow}{while}(Count+Size < String->Length)
00346     \{
00347         \textcolor{keywordflow}{if}(memcmp(String->String+Count, Search, Size) == 0)
00348             \textcolor{keywordflow}{return} Count;
00349         ++Count;
00350     \}
00351     \textcolor{keywordflow}{return} -1;
00352 \}
00353 \textcolor{keywordtype}{int} S\_FindLast(S_String *String, \textcolor{keywordtype}{char} *Search);
00354 \textcolor{keywordtype}{int} S\_FindFirstS(S_String *String, S_String *Search);
00355 \textcolor{keywordtype}{int} S\_FindLastS(S_String *String, S_String *Search);
00356 \textcolor{keywordtype}{int} S\_FindFirstSafe(S_String *String, \textcolor{keywordtype}{char} *Search, \textcolor{keywordtype}{int} Length);
00357 \textcolor{keywordtype}{int} S\_FindLastSafe(S_String *String, \textcolor{keywordtype}{char} *Search, \textcolor{keywordtype}{int} Length);
00358 
00359 \textcolor{keywordtype}{void} S\_ToUpper(S_String *String)
00360 \{
00361     \textcolor{keywordtype}{int} Count;
00362     \textcolor{keywordflow}{for}(Count = 0; Count < String->Length; ++Count)
00363         \textcolor{keywordflow}{if}(islower(String->String[Count]))String->String[Count] = toupper(String-
      >String[Count]);
00364 \}
00365 
00366 \textcolor{keywordtype}{void} S\_Strip(S_String *String)
00367 \{
00368     \textcolor{comment}{/* Remove all of the whitespace from the start and end of the string */}
00369     \textcolor{keywordtype}{int} ResultingLength = String->Length, Index, StartOffset = 0;
00370     \textcolor{keywordflow}{for}(Index = 0; Index < String->Length; ++Index)
00371     \{
00372         \textcolor{keywordflow}{if}(String->String[Index] == 10 || String->String[Index] == 13 ||
00373         String->String[Index] == 32 || String->String[Index] == 9)
00374         \{
00375             ++StartOffset;
00376             --ResultingLength;
00377         \}
00378         \textcolor{keywordflow}{else}
00379             \textcolor{keywordflow}{break};
00380     \}
00381     \textcolor{keywordflow}{for}(Index = String->Length - 1; Index >= 0; --Index)
00382     \{
00383         \textcolor{keywordflow}{if}(String->String[Index] == 10 || String->String[Index] == 13 ||
00384         String->String[Index] == 32 || String->String[Index] == 9)
00385         \{
00386             --ResultingLength;
00387         \}
00388         \textcolor{keywordflow}{else}
00389             \textcolor{keywordflow}{break};
00390     \}
00391     memmove(String->String, String->String+StartOffset, ResultingLength);
00392     String->Length = ResultingLength;
00393 \}
00394 
00395 \textcolor{keywordtype}{int} S\_PadFront(S_String *Str, \textcolor{keywordtype}{int} Length, \textcolor{keywordtype}{char} PadChar)
00396 \{
00397     \textcolor{keywordflow}{if}(Str->Length >= Length) \textcolor{comment}{/* The string does not need to be padded... */}
00398         \textcolor{keywordflow}{return} 0;
00399     \textcolor{keywordflow}{if}(StrCheckRealloc(Str, Length) == -1)
00400         \textcolor{keywordflow}{return} -1;
00401     \textcolor{keywordtype}{char} Temp[Length-Str->Length];
00402     \textcolor{comment}{/* Was using memset here, until IllegalInstruction exceptions were being thro
      wn. FML */}
00403     \textcolor{keywordtype}{int} Index = 0;
00404     \textcolor{keywordflow}{while}(Index < Length - Str->Length)
00405         Temp[Index++] = PadChar;
00406     \textcolor{keywordflow}{return} S\_PrependStringSafe(Str, Temp, Length-Str->Length);
00407 \}
00408 
00409 
\end{alltt}\end{footnotesize}
